<meta charset="utf-8" />
<pre>
<script>
function is64Bit() {
  const x64 = ['x86_64', 'x86-64', 'Win64','x64', 'amd64', 'AMD64'];
  for (const substr of x64) if (navigator.userAgent.includes(substr)) return true;
  return navigator.platform === 'Linux x86_64' || navigator.platform === 'MacIntel';
}

function wasmInfo() {
  var info = {
    WebAssembly: typeof WebAssembly,
    SharedArrayBuffer: typeof SharedArrayBuffer,
    Atomics: typeof Atomics
  };

  if (info.WebAssembly !== 'object') return info;

  info.validate = typeof WebAssembly.validate;
  if (info.validate !== 'function') return info;

  var source = Uint8Array.of(0x0, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00);
  info.mvp = WebAssembly.validate(source);
  if (!info.mvp) return info;

  info.simd = {
    'i32x4.dot_i16x8_s': WebAssembly.validate(Uint8Array.of(0, 97, 115, 109, 1, 0, 0, 0, 1, 5, 1, 96, 0, 1, 123, 3, 2, 1, 0, 7, 8, 1, 4, 116, 101, 115, 116, 0, 0, 10, 15, 1, 13, 0, 65, 0, 253, 17, 65, 0, 253, 17, 253, 186, 1, 11))
  };

  if (info.SharedArrayBuffer !== 'function') return info;
  var mem = new WebAssembly.Memory({shared: true, initial: 8, maximum: 16});
  info.sharedMem = mem.buffer instanceof SharedArrayBuffer;

  try {
    window.postMessage(mem, '*');
    info.structuredCloning = 'ok';
  } catch (e) {
    info.structuredCloning = e.toString();
  }

  try {
    mem.grow(8);
    info.growableMem = 'ok';
  } catch (e) {
    info.growableMem = e.toString();
  }

  return info;
}

function localStorageInfo() {
  var interesting = [
    'client-eval-enabled',
    'analyse.ceval.max-depth',
    'analyse.ceval.multipv',
    'analyse.ceval.threads',
    'analyse.ceval.hash-size',
    'analyse.ceval.infinite',
    'analyse.ceval.enable-nnue',
    'just-notified',
    'push-subscribed',
    'grid',
    'resize-nag',
    'speech.enabled',
    'sound-volume',
    'surl7'
  ];
  var info = {};
  for (var i = 0; i < interesting.length; i++) {
    info[interesting[i]] = window.localStorage.getItem(interesting[i]);
  }
  return info;
}

function serviceWorkerInfo() {
  var info = {
    'navigator': 'serviceWorker' in navigator,
    'permissions': 'permissions' in navigator,
    'Notification': 'Notification' in window,
    'PushManager': 'PushManager' in window,
    'fetch': typeof fetch
  };

  if (info.Notification) info['Notification.permission'] = Notification.permission;

  return info;
}

var info = {
  diagnosticsVersion: 6,
  navigator: {
    userAgent: navigator.userAgent,
    platform: navigator.platform,
    chrome: !!window.chrome,
    is64Bit: is64Bit(),
    hardwareConcurrency: navigator.hardwareConcurrency,
    deviceMemory: navigator.deviceMemory,
    connection: navigator.connection && {
      saveData: navigator.connection.saveData
    }
  },
  wasm: wasmInfo(),
  hasTouchEvents: 'ontouchstart' in window,
  animate: typeof document.createElement('div').animate,
  localStorage: localStorageInfo(),
  serviceWorker: serviceWorkerInfo()
};

document.write(JSON.stringify(info));
</script>
</pre>
